home *** CD-ROM | disk | FTP | other *** search
- Subject: v15i038: Stevie, an "aspiring" VI clone for Unix, OS/2, Amiga, Part02/04
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: onecom!wldrdg!tony (Tony Andrews)
- Posting-number: Volume 15, Issue 38
- Archive-name: stevie/part02
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 4)."
- # Contents: cmdline.c edit.c help.c main.c misccmds.c
- # Wrapped by rsalz@fig.bbn.com on Sun Jun 5 11:45:43 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'cmdline.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cmdline.c'\"
- else
- echo shar: Extracting \"'cmdline.c'\" \(11004 characters\)
- sed "s/^X//" >'cmdline.c' <<'END_OF_FILE'
- X/*
- X * STevie - ST editor for VI enthusiasts. ...Tim Thompson...twitch!tjt...
- X *
- X * Extensive modifications by: Tony Andrews onecom!wldrdg!tony
- X *
- X */
- X
- X#include "stevie.h"
- X
- static char *altfile = NULL; /* alternate file */
- static int altline; /* line # in alternate file */
- X
- static char *nowrtmsg = "No write since last change (use ! to override)";
- X
- extern char **files; /* used for "n" and "rew" */
- extern int numfiles, curfile;
- X
- X/*
- X * The next two variables contain the bounds of any range given in a
- X * command. If no range was given, both contain null line pointers.
- X * If only a single line was given, u_pos will contain a null line
- X * pointer.
- X */
- static LPTR l_pos, u_pos;
- X
- static bool_t interactive; /* TRUE if we're reading a real command line */
- X
- X#define CMDSZ 100 /* size of the command buffer */
- X
- static bool_t doecmd();
- static void badcmd(), doshell(), get_range();
- static LPTR *get_line();
- X
- X#ifdef MEGAMAX
- overlay "cmdline"
- X#endif
- X
- X/*
- X * readcmdline() - accept a command line starting with ':', '/', or '?'
- X *
- X * readcmdline() accepts and processes colon commands and searches. If
- X * 'cmdline' is null, the command line is read here. Otherwise, cmdline
- X * points to a complete command line that should be used. This is used
- X * in main() to handle initialization commands in the environment variable
- X * "EXINIT".
- X */
- void
- readcmdline(firstc, cmdline)
- int firstc; /* either ':', '/', or '?' */
- char *cmdline; /* optional command string */
- X{
- X int c;
- X char buff[CMDSZ];
- X char *p, *q, *cmd, *arg;
- X
- X /*
- X * Clear the range variables.
- X */
- X l_pos.linep = (struct line *) NULL;
- X u_pos.linep = (struct line *) NULL;
- X
- X interactive = (cmdline == NULL);
- X
- X if (interactive)
- X gotocmd(1,1,firstc);
- X p = buff;
- X if ( firstc != ':' )
- X *p++ = firstc;
- X
- X if (interactive) {
- X /* collect the command string, handling '\b' and @ */
- X for ( ; ; ) {
- X c = vgetc();
- X if ( c=='\n'||c=='\r'||c==EOF )
- X break;
- X if ( c=='\b' ) {
- X if ( p > buff ) {
- X p--;
- X /* this is gross, but it relies
- X * only on 'gotocmd'
- X */
- X gotocmd(1,0,firstc==':'?':':0);
- X for ( q=buff; q<p; q++ )
- X outchar(*q);
- X } else {
- X msg("");
- X return; /* back to cmd mode */
- X }
- X continue;
- X }
- X if ( c=='@' ) {
- X p = buff;
- X gotocmd(1,1,firstc);
- X continue;
- X }
- X outchar(c);
- X *p++ = c;
- X }
- X *p = '\0';
- X } else {
- X if (strlen(cmdline) > CMDSZ-2) /* should really do something */
- X return; /* better here... */
- X strcpy(p, cmdline);
- X }
- X
- X /* skip any initial white space */
- X for ( cmd = buff; *cmd != NUL && isspace(*cmd); cmd++ )
- X ;
- X
- X /* search commands */
- X c = *cmd;
- X if ( c == '/' || c == '?' ) {
- X cmd++;
- X if ( *cmd == c ) {
- X /* the command was '//' or '??' */
- X repsearch();
- X return;
- X }
- X /* If there is a matching '/' or '?' at the end, toss it */
- X p = strchr(cmd, NUL);
- X if ( *(p-1) == c && *(p-2) != '\\' )
- X *(p-1) = NUL;
- X dosearch((c == '/') ? FORWARD : BACKWARD, cmd);
- X return;
- X }
- X
- X /*
- X * Parse a range, if present (and update the cmd pointer).
- X */
- X get_range(&cmd);
- X
- X /* isolate the command and find any argument */
- X for ( p=cmd; *p != NUL && ! isspace(*p); p++ )
- X ;
- X if ( *p == NUL )
- X arg = NULL;
- X else {
- X *p = NUL;
- X for (p++; *p != NUL && isspace(*p) ;p++)
- X ;
- X arg = p;
- X if ( *arg == '\0' )
- X arg = NULL;
- X }
- X if ( strcmp(cmd,"q!")==0 )
- X getout();
- X if ( strcmp(cmd,"q")==0 ) {
- X if ( Changed )
- X emsg(nowrtmsg);
- X else
- X getout();
- X return;
- X }
- X if ( strcmp(cmd,"w")==0 ) {
- X if ( arg == NULL ) {
- X if (Filename != NULL) {
- X writeit(Filename, &l_pos, &u_pos);
- X UNCHANGED;
- X } else
- X emsg("No output file");
- X }
- X else
- X writeit(arg, &l_pos, &u_pos);
- X return;
- X }
- X if ( strcmp(cmd,"wq")==0 ) {
- X if (Filename != NULL) {
- X if ( writeit(Filename, NULL, NULL) )
- X getout();
- X } else
- X emsg("No output file");
- X return;
- X }
- X if ( strcmp(cmd, "x") == 0 ) {
- X if (Changed) {
- X if (Filename != NULL) {
- X if (!writeit(Filename, NULL, NULL))
- X return;
- X } else {
- X emsg("No output file");
- X return;
- X }
- X }
- X getout();
- X }
- X if ( strcmp(cmd,"f")==0 && arg==NULL ) {
- X fileinfo();
- X return;
- X }
- X if ( *cmd == 'n' ) {
- X if ( (curfile + 1) < numfiles ) {
- X /*
- X * stuff ":e[!] FILE\n"
- X */
- X stuffin(":e");
- X if (cmd[1] == '!')
- X stuffin("!");
- X stuffin(" ");
- X stuffin(files[++curfile]);
- X stuffin("\n");
- X } else
- X emsg("No more files!");
- X return;
- X }
- X if ( *cmd == 'p' ) {
- X if ( curfile > 0 ) {
- X /*
- X * stuff ":e[!] FILE\n"
- X */
- X stuffin(":e");
- X if (cmd[1] == '!')
- X stuffin("!");
- X stuffin(" ");
- X stuffin(files[--curfile]);
- X stuffin("\n");
- X } else
- X emsg("No more files!");
- X return;
- X }
- X if ( strncmp(cmd, "rew", 3) == 0) {
- X if (numfiles <= 1) /* nothing to rewind */
- X return;
- X curfile = 0;
- X /*
- X * stuff ":e[!] FILE\n"
- X */
- X stuffin(":e");
- X if (cmd[3] == '!')
- X stuffin("!");
- X stuffin(" ");
- X stuffin(files[0]);
- X stuffin("\n");
- X return;
- X }
- X if ( strcmp(cmd,"e") == 0 || strcmp(cmd,"e!") == 0 ) {
- X doecmd(arg, cmd[1] == '!');
- X return;
- X }
- X if ( strcmp(cmd,"f") == 0 ) {
- X Filename = strsave(arg);
- X filemess("");
- X return;
- X }
- X if ( strcmp(cmd,"r") == 0 || strcmp(cmd,".r") == 0 ) {
- X if ( arg == NULL ) {
- X badcmd();
- X return;
- X }
- X if (readfile(arg, Curschar, 1)) {
- X emsg("Can't open file");
- X return;
- X }
- X updatescreen();
- X CHANGED;
- X return;
- X }
- X if ( strcmp(cmd,".=")==0 ) {
- X char messbuff[80];
- X sprintf(messbuff,"line %d", cntllines(Filemem,Curschar));
- X msg(messbuff);
- X return;
- X }
- X if ( strcmp(cmd,"$=")==0 ) {
- X char messbuff[8];
- X sprintf(messbuff, "%d", cntllines(Filemem, Fileend)-1);
- X msg(messbuff);
- X return;
- X }
- X if ( strncmp(cmd,"ta", 2) == 0 ) {
- X dotag(arg, cmd[2] == '!');
- X return;
- X }
- X if ( strcmp(cmd,"set")==0 ) {
- X doset(arg, interactive);
- X return;
- X }
- X if ( strcmp(cmd,"help")==0 ) {
- X if (help()) {
- X screenclear();
- X updatescreen();
- X }
- X return;
- X }
- X if ( strcmp(cmd, "version") == 0) {
- X extern char *Version;
- X
- X msg(Version);
- X return;
- X }
- X if ( strcmp(cmd, "sh") == 0) {
- X doshell();
- X return;
- X }
- X /*
- X * If we got a line, but no command, then go to the line.
- X */
- X if (*cmd == NUL && l_pos.linep != NULL) {
- X *Curschar = l_pos;
- X cursupdate();
- X return;
- X }
- X
- X badcmd();
- X}
- X
- X/*
- X * get_range - parse a range specifier
- X *
- X * Ranges are of the form:
- X *
- X * addr[,addr]
- X *
- X * where 'addr' is:
- X *
- X * $ [+- NUM]
- X * 'x [+- NUM] (where x denotes a currently defined mark)
- X * . [+- NUM]
- X * NUM
- X *
- X * The pointer *cp is updated to point to the first character following
- X * the range spec. If an initial address is found, but no second, the
- X * upper bound is equal to the lower.
- X */
- static void
- get_range(cp)
- char **cp;
- X{
- X LPTR *l;
- X char *p;
- X
- X if ((l = get_line(cp)) == NULL)
- X return;
- X
- X l_pos = *l;
- X
- X for (p = *cp; *p != NUL && isspace(*p) ;p++)
- X ;
- X
- X *cp = p;
- X
- X if (*p != ',') { /* is there another line spec ? */
- X u_pos = l_pos;
- X return;
- X }
- X
- X *cp = ++p;
- X
- X if ((l = get_line(cp)) == NULL) {
- X u_pos = l_pos;
- X return;
- X }
- X
- X u_pos = *l;
- X}
- X
- static LPTR *
- get_line(cp)
- char **cp;
- X{
- X static LPTR pos;
- X LPTR *lp;
- X char *p, c;
- X int lnum;
- X
- X pos.index = 0; /* shouldn't matter... check back later */
- X
- X p = *cp;
- X /*
- X * Determine the basic form, if present.
- X */
- X switch (c = *p++) {
- X
- X case '$':
- X pos.linep = Fileend->linep->prev;
- X break;
- X
- X case '.':
- X pos.linep = Curschar->linep;
- X break;
- X
- X case '\'':
- X if ((lp = getmark(*p++)) == NULL) {
- X emsg("Unknown mark");
- X return (LPTR *) NULL;
- X }
- X pos = *lp;
- X break;
- X
- X case '0': case '1': case '2': case '3': case '4':
- X case '5': case '6': case '7': case '8': case '9':
- X for (lnum = c - '0'; isdigit(*p) ;p++)
- X lnum = (lnum * 10) + (*p - '0');
- X
- X pos = *gotoline(lnum);
- X break;
- X
- X default:
- X return (LPTR *) NULL;
- X }
- X
- X while (*p != NUL && isspace(*p))
- X p++;
- X
- X if (*p == '-' || *p == '+') {
- X bool_t neg = (*p++ == '-');
- X
- X for (lnum = 0; isdigit(*p) ;p++)
- X lnum = (lnum * 10) + (*p - '0');
- X
- X if (neg)
- X lnum = -lnum;
- X
- X pos = *gotoline( cntllines(Filemem, &pos) + lnum );
- X }
- X
- X *cp = p;
- X return &pos;
- X}
- X
- static void
- badcmd()
- X{
- X if (interactive)
- X emsg("Unrecognized command");
- X}
- X
- X#define LSIZE 512 /* max. size of a line in the tags file */
- X
- X/*
- X * dotag(tag, force) - goto tag
- X */
- void
- dotag(tag, force)
- char *tag;
- bool_t force;
- X{
- X FILE *tp, *fopen();
- X char lbuf[LSIZE];
- X char *fname, *str;
- X
- X if ((tp = fopen("tags", "r")) == NULL) {
- X emsg("Can't open tags file");
- X return;
- X }
- X
- X while (fgets(lbuf, LSIZE, tp) != NULL) {
- X
- X if ((fname = strchr(lbuf, TAB)) == NULL) {
- X emsg("Format error in tags file");
- X return;
- X }
- X *fname++ = '\0';
- X if ((str = strchr(fname, TAB)) == NULL) {
- X emsg("Format error in tags file");
- X return;
- X }
- X *str++ = '\0';
- X
- X if (strcmp(lbuf, tag) == 0) {
- X if (doecmd(fname, force)) {
- X stuffin(str); /* str has \n at end */
- X stuffin("\007"); /* CTRL('G') */
- X fclose(tp);
- X return;
- X }
- X }
- X }
- X emsg("tag not found");
- X fclose(tp);
- X}
- X
- static bool_t
- doecmd(arg, force)
- char *arg;
- bool_t force;
- X{
- X int line = 1; /* line # to go to in new file */
- X
- X if (!force && Changed) {
- X emsg(nowrtmsg);
- X return FALSE;
- X }
- X if ( arg != NULL ) {
- X /*
- X * First detect a ":e" on the current file. This is mainly
- X * for ":ta" commands where the destination is within the
- X * current file.
- X */
- X if (Filename != NULL && strcmp(arg, Filename) == 0) {
- X if (!Changed || (Changed && !force))
- X return TRUE;
- X }
- X if (strcmp(arg, "#") == 0) { /* alternate */
- X char *s = Filename;
- X
- X if (altfile == NULL) {
- X emsg("No alternate file");
- X return FALSE;
- X }
- X Filename = altfile;
- X altfile = s;
- X line = altline;
- X altline = cntllines(Filemem, Curschar);
- X } else {
- X altfile = Filename;
- X altline = cntllines(Filemem, Curschar);
- X Filename = strsave(arg);
- X }
- X }
- X if (Filename == NULL) {
- X emsg("No filename");
- X return FALSE;
- X }
- X
- X /* clear mem and read file */
- X freeall();
- X filealloc();
- X UNCHANGED;
- X
- X readfile(Filename, Filemem, 0);
- X *Topchar = *Curschar;
- X if (line != 1) {
- X stuffnum(line);
- X stuffin("G");
- X }
- X setpcmark();
- X updatescreen();
- X return TRUE;
- X}
- X
- static void
- doshell()
- X{
- X char *sh, *getenv();
- X
- X if ((sh = getenv("SHELL")) == NULL) {
- X emsg("Shell variable not set");
- X return;
- X }
- X gotocmd(TRUE, FALSE, 0);
- X
- X if (system(sh) < 0) {
- X emsg("Exec failed");
- X return;
- X }
- X
- X wait_return();
- X}
- X
- void
- gotocmd(clr, fresh, firstc)
- bool_t clr, fresh;
- char firstc;
- X{
- X int n;
- X
- X windgoto(Rows-1,0);
- X if ( clr )
- X outstr(T_EL); /* clear the bottom line */
- X if ( firstc )
- X outchar(firstc);
- X}
- X
- X/*
- X * msg(s) - displays the string 's' on the status line
- X */
- void
- msg(s)
- char *s;
- X{
- X gotocmd(TRUE, TRUE, 0);
- X outstr(s);
- X}
- X
- void
- smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9)
- char *s;
- int a1, a2, a3, a4, a5, a6, a7, a8, a9;
- X{
- X char sbuf[80];
- X
- X sprintf(sbuf, s, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- X msg(sbuf);
- X}
- X
- X/*
- X * emsg() - display an error message
- X *
- X * Rings the bell, if appropriate, and calls message() to do the real work
- X */
- void
- emsg(s)
- char *s;
- X{
- X if (P(P_EB))
- X beep();
- X msg(s);
- X}
- X
- void
- wait_return()
- X{
- X char c;
- X
- X outstr("Press RETURN to continue");
- X do {
- X c = vgetc();
- X } while (c != '\r' && c != '\n');
- X
- X screenclear();
- X updatescreen();
- X}
- END_OF_FILE
- if test 11004 -ne `wc -c <'cmdline.c'`; then
- echo shar: \"'cmdline.c'\" unpacked with wrong size!
- fi
- # end of 'cmdline.c'
- fi
- if test -f 'edit.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'edit.c'\"
- else
- echo shar: Extracting \"'edit.c'\" \(6480 characters\)
- sed "s/^X//" >'edit.c' <<'END_OF_FILE'
- X/*
- X * STevie - ST editor for VI enthusiasts. ...Tim Thompson...twitch!tjt...
- X *
- X * Extensive modifications by: Tony Andrews onecom!wldrdg!tony
- X *
- X */
- X
- X#include "stevie.h"
- X
- X/*
- X * This flag is used to make auto-indent work right on lines where only
- X * a <RETURN> or <ESC> is typed. It is set when an auto-indent is done,
- X * and reset when any other editting is done on the line. If an <ESC>
- X * or <RETURN> is received, and did_ai is TRUE, the line is truncated.
- X */
- bool_t did_ai = FALSE;
- X
- void
- edit()
- X{
- X int c;
- X char *p, *q;
- X
- X Prenum = 0;
- X
- X /* position the display and the cursor at the top of the file. */
- X *Topchar = *Filemem;
- X *Curschar = *Filemem;
- X Cursrow = Curscol = 0;
- X
- X for ( ;; ) {
- X
- X /* Figure out where the cursor is based on Curschar. */
- X cursupdate();
- X
- X windgoto(Cursrow,Curscol);
- X
- X c = vgetc();
- X
- X if (State == NORMAL) {
- X
- X /* We're in the normal (non-insert) mode. */
- X
- X /* Pick up any leading digits and compute 'Prenum' */
- X if ( (Prenum>0 && isdigit(c)) || (isdigit(c) && c!='0') ){
- X Prenum = Prenum*10 + (c-'0');
- X continue;
- X }
- X /* execute the command */
- X normal(c);
- X Prenum = 0;
- X
- X } else {
- X
- X switch (c) { /* We're in insert mode */
- X
- X case ESC: /* an escape ends input mode */
- X
- X set_want_col = TRUE;
- X
- X /* Don't end up on a '\n' if you can help it. */
- X if (gchar(Curschar) == NUL && Curschar->index != 0)
- X dec(Curschar);
- X
- X /*
- X * The cursor should end up on the last inserted
- X * character. This is an attempt to match the real
- X * 'vi', but it may not be quite right yet.
- X */
- X if (Curschar->index != 0 && !endofline(Curschar))
- X dec(Curschar);
- X
- X State = NORMAL;
- X msg("");
- X *Uncurschar = *Insstart;
- X Undelchars = Ninsert;
- X /* Undobuff[0] = '\0'; */
- X /* construct the Redo buffer */
- X p=Redobuff;
- X q=Insbuff;
- X while ( q < Insptr )
- X *p++ = *q++;
- X *p++ = ESC;
- X *p = NUL;
- X updatescreen();
- X break;
- X
- X case CTRL('D'):
- X /*
- X * Control-D is treated as a backspace in insert
- X * mode to make auto-indent easier. This isn't
- X * completely compatible with vi, but it's a lot
- X * easier than doing it exactly right, and the
- X * difference isn't very noticeable.
- X */
- X case BS:
- X /* can't backup past starting point */
- X if (Curschar->linep == Insstart->linep &&
- X Curschar->index <= Insstart->index) {
- X beep();
- X break;
- X }
- X
- X /* can't backup to a previous line */
- X if (Curschar->linep != Insstart->linep &&
- X Curschar->index <= 0) {
- X beep();
- X break;
- X }
- X
- X did_ai = FALSE;
- X dec(Curschar);
- X delchar(TRUE);
- X Insptr--;
- X Ninsert--;
- X cursupdate();
- X updateline();
- X break;
- X
- X case CR:
- X case NL:
- X *Insptr++ = NL;
- X Ninsert++;
- X opencmd(FORWARD, TRUE); /* open a new line */
- X cursupdate();
- X updatescreen();
- X break;
- X
- X default:
- X did_ai = FALSE;
- X insertchar(c);
- X break;
- X }
- X }
- X }
- X}
- X
- X/*
- X * Special characters in this context are those that need processing other
- X * than the simple insertion that can be performed here. This includes ESC
- X * which terminates the insert, and CR/NL which need special processing to
- X * open up a new line. This routine tries to optimize insertions performed
- X * by the "redo" command, so it needs to know when it should stop and defer
- X * processing to the "normal" mechanism.
- X */
- X#define ISSPECIAL(c) ((c) == NL || (c) == CR || (c) == ESC)
- X
- void
- insertchar(c)
- int c;
- X{
- X char *p;
- X
- X if ( ! anyinput() ) {
- X inschar(c);
- X *Insptr++ = c;
- X Ninsert++;
- X /*
- X * The following kludge avoids overflowing the statically
- X * allocated insert buffer. Just dump the user back into
- X * command mode, and print a message.
- X */
- X if (Insptr+10 >= &Insbuff[1024]) {
- X stuffin(mkstr(ESC));
- X emsg("No buffer space - returning to command mode");
- X sleep(2);
- X }
- X }
- X else {
- X /* If there's any pending input, grab it all at once. */
- X p = Insptr;
- X *Insptr++ = c;
- X Ninsert++;
- X for (c = vpeekc(); !ISSPECIAL(c) ;c = vpeekc()) {
- X c = vgetc();
- X *Insptr++ = c;
- X Ninsert++;
- X }
- X *Insptr = '\0';
- X insstr(p);
- X }
- X updateline();
- X}
- X
- void
- getout()
- X{
- X windgoto(Rows-1,0);
- X putchar('\r');
- X putchar('\n');
- X windexit(0);
- X}
- X
- void
- scrolldown(nlines)
- int nlines;
- X{
- X register LPTR *p;
- X register int done = 0; /* total # of physical lines done */
- X
- X /* Scroll up 'nlines' lines. */
- X while (nlines--) {
- X if ((p = prevline(Topchar)) == NULL)
- X break;
- X done += plines(p);
- X *Topchar = *p;
- X if (Curschar->linep == Botchar->linep->prev)
- X *Curschar = *prevline(Curschar);
- X }
- X s_ins(0, done);
- X}
- X
- void
- scrollup(nlines)
- int nlines;
- X{
- X register LPTR *p;
- X register int done = 0; /* total # of physical lines done */
- X register int pl; /* # of plines for the current line */
- X
- X /* Scroll down 'nlines' lines. */
- X while (nlines--) {
- X pl = plines(Topchar);
- X if ((p = nextline(Topchar)) == NULL)
- X break;
- X done += pl;
- X if (Curschar->linep == Topchar->linep)
- X *Curschar = *p;
- X *Topchar = *p;
- X
- X }
- X s_del(0, done);
- X}
- X
- X/*
- X * oneright
- X * oneleft
- X * onedown
- X * oneup
- X *
- X * Move one char {right,left,down,up}. Return TRUE when
- X * sucessful, FALSE when we hit a boundary (of a line, or the file).
- X */
- X
- bool_t
- oneright()
- X{
- X set_want_col = TRUE;
- X
- X switch (inc(Curschar)) {
- X
- X case 0:
- X return TRUE;
- X
- X case 1:
- X dec(Curschar); /* crossed a line, so back up */
- X /* fall through */
- X case -1:
- X return FALSE;
- X }
- X}
- X
- bool_t
- oneleft()
- X{
- X set_want_col = TRUE;
- X
- X switch (dec(Curschar)) {
- X
- X case 0:
- X return TRUE;
- X
- X case 1:
- X inc(Curschar); /* crossed a line, so back up */
- X /* fall through */
- X case -1:
- X return FALSE;
- X }
- X}
- X
- void
- beginline(flag)
- bool_t flag;
- X{
- X while ( oneleft() )
- X ;
- X if (flag) {
- X while (isspace(gchar(Curschar)) && oneright())
- X ;
- X }
- X set_want_col = TRUE;
- X}
- X
- bool_t
- oneup(n)
- X{
- X LPTR p, *np;
- X int k;
- X
- X p = *Curschar;
- X for ( k=0; k<n; k++ ) {
- X /* Look for the previous line */
- X if ( (np=prevline(&p)) == NULL ) {
- X /* If we've at least backed up a little .. */
- X if ( k > 0 )
- X break; /* to update the cursor, etc. */
- X else
- X return FALSE;
- X }
- X p = *np;
- X }
- X *Curschar = p;
- X /* This makes sure Topchar gets updated so the complete line */
- X /* is one the screen. */
- X cursupdate();
- X /* try to advance to the column we want to be at */
- X *Curschar = *coladvance(&p, Curswant);
- X return TRUE;
- X}
- X
- bool_t
- onedown(n)
- X{
- X LPTR p, *np;
- X int k;
- X
- X p = *Curschar;
- X for ( k=0; k<n; k++ ) {
- X /* Look for the next line */
- X if ( (np=nextline(&p)) == NULL ) {
- X if ( k > 0 )
- X break;
- X else
- X return FALSE;
- X }
- X p = *np;
- X }
- X /* try to advance to the column we want to be at */
- X *Curschar = *coladvance(&p, Curswant);
- X return TRUE;
- X}
- END_OF_FILE
- if test 6480 -ne `wc -c <'edit.c'`; then
- echo shar: \"'edit.c'\" unpacked with wrong size!
- fi
- # end of 'edit.c'
- fi
- if test -f 'help.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'help.c'\"
- else
- echo shar: Extracting \"'help.c'\" \(8348 characters\)
- sed "s/^X//" >'help.c' <<'END_OF_FILE'
- X/*
- X * STevie - ST editor for VI enthusiasts. ...Tim Thompson...twitch!tjt...
- X *
- X * Extensive modifications by: Tony Andrews onecom!wldrdg!tony
- X *
- X */
- X
- X#include "stevie.h"
- X
- char *Version = "STEVIE - Version 3.10";
- X
- static int helprow;
- X
- X#ifdef HELP
- X
- X#ifdef MEGAMAX
- overlay "help"
- X#endif
- X
- static void longline();
- X
- bool_t
- help()
- X{
- X
- X/***********************************************************************
- X * First Screen: Positioning within file, Adjusting the Screen
- X ***********************************************************************/
- X
- X outstr(T_ED);
- X windgoto(helprow = 0, 0);
- X
- longline("\
- X Positioning within file\n\
- X =======================\n\
- X ^F Forward screenfull Original version by:\n\
- X ^B Backward screenfull Tim Thompson\n");
- longline("\
- X ^D scroll down half screen\n\
- X ^U scroll up half screen Extensive hacks by:\n");
- longline("\
- X G Goto line (end default) Tony Andrews\n\
- X ]] next function\n\
- X [[ previous function\n\
- X /re next occurence of regular expression 're'\n");
- longline("\
- X ?re prior occurence of regular expression 're'\n\
- X n repeat last / or ?\n\
- X N reverse last / or ?\n\
- X % find matching (, ), {, }, [, or ]\n");
- longline("\
- X\n\
- X Adjusting the screen\n\
- X ====================\n\
- X ^L Redraw the screen\n\
- X ^E scroll window down 1 line\n\
- X ^Y scroll window up 1 line\n");
- longline("\
- X z<RETURN> redraw, current line at top\n\
- X z- ... at bottom\n\
- X z. ... at center\n");
- X
- X windgoto(0, 52);
- X longline(Version);
- X
- X windgoto(helprow = Rows-2, 47);
- X longline("<Press space bar to continue>\n");
- X windgoto(helprow = Rows-1, 47);
- X longline("<Any other key will quit>");
- X
- X if ( vgetc() != ' ' )
- X return TRUE;
- X
- X/***********************************************************************
- X * Second Screen: Character positioning
- X ***********************************************************************/
- X
- X outstr(T_ED);
- X windgoto(helprow = 0, 0);
- X
- longline("\
- X Character Positioning\n\
- X =====================\n\
- X ^ first non-white\n\
- X 0 beginning of line\n\
- X $ end of line\n\
- X h backward\n");
- longline("\
- X l forward\n\
- X ^H same as h\n\
- X space same as l\n\
- X fx find 'x' forward\n");
- longline("\
- X Fx find 'x' backward\n\
- X tx upto 'x' forward\n\
- X Tx upto 'x' backward\n\
- X ; Repeat last f, F, t, or T\n");
- longline("\
- X , inverse of ;\n\
- X | to specified column\n\
- X % find matching (, ), {, }, [, or ]\n");
- X
- X windgoto(helprow = Rows-2, 47);
- X longline("<Press space bar to continue>\n");
- X windgoto(helprow = Rows-1, 47);
- X longline("<Any other key will quit>");
- X
- X if ( vgetc() != ' ' )
- X return TRUE;
- X
- X/***********************************************************************
- X * Third Screen: Line Positioning, Marking and Returning
- X ***********************************************************************/
- X
- X outstr(T_ED);
- X windgoto(helprow = 0, 0);
- X
- longline("\
- X Line Positioning\n\
- X =====================\n\
- X H home window line\n\
- X L last window line\n\
- X M middle window line\n");
- longline("\
- X + next line, at first non-white\n\
- X - previous line, at first non-white\n\
- X CR return, same as +\n\
- X j next line, same column\n\
- X k previous line, same column\n");
- X
- longline("\
- X\n\
- X Marking and Returning\n\
- X =====================\n\
- X `` previous context\n\
- X '' ... at first non-white in line\n");
- longline("\
- X mx mark position with letter 'x'\n\
- X `x to mark 'x'\n\
- X 'x ... at first non-white in line\n");
- X
- X windgoto(helprow = Rows-2, 47);
- X longline("<Press space bar to continue>\n");
- X windgoto(helprow = Rows-1, 47);
- X longline("<Any other key will quit>");
- X
- X if ( vgetc() != ' ' )
- X return TRUE;
- X/***********************************************************************
- X * Fourth Screen: Insert & Replace,
- X ***********************************************************************/
- X
- X outstr(T_ED);
- X windgoto(helprow = 0, 0);
- X
- longline("\
- X Insert and Replace\n\
- X ==================\n\
- X a append after cursor\n\
- X i insert before cursor\n\
- X A append at end of line\n\
- X I insert before first non-blank\n");
- longline("\
- X o open line below\n\
- X O open line above\n\
- X rx replace single char with 'x'\n\
- X R replace characters (not yet)\n");
- X
- longline("\
- X\n\
- X Words, sentences, paragraphs\n\
- X ============================\n\
- X w word forward\n\
- X b back word\n\
- X e end of word\n\
- X ) to next sentence (not yet)\n\
- X } to next paragraph (not yet)\n");
- longline("\
- X ( back sentence (not yet)\n\
- X { back paragraph (not yet)\n\
- X W blank delimited word\n\
- X B back W\n\
- X E to end of W\n");
- X
- X windgoto(helprow = Rows-2, 47);
- X longline("<Press space bar to continue>\n");
- X windgoto(helprow = Rows-1, 47);
- X longline("<Any other key will quit>");
- X
- X if ( vgetc() != ' ' )
- X return TRUE;
- X
- X/***********************************************************************
- X * Fifth Screen: Misc. operations,
- X ***********************************************************************/
- X
- X outstr(T_ED);
- X windgoto(helprow = 0, 0);
- X
- longline("\
- X Undo & Redo\n\
- X =============\n\
- X u undo last change (partially done)\n\
- X U restore current line (not yet)\n\
- X . repeat last change\n");
- X
- longline("\
- X\n\
- X File manipulation\n\
- X =================\n");
- longline("\
- X :w write back changes\n\
- X :wq write and quit\n\
- X :x write if modified, and quit\n\
- X :q quit\n\
- X :q! quit, discard changes\n\
- X :e name edit file 'name'\n");
- longline("\
- X :e! reedit, discard changes\n\
- X :e # edit alternate file\n\
- X :w name write file 'name'\n");
- longline("\
- X :n edit next file in arglist\n\
- X :n args specify new arglist (not yet)\n\
- X :rew rewind arglist\n\
- X :f show current file and lines\n");
- longline("\
- X :f file change current file name\n\
- X :ta tag to tag file entry 'tag'\n\
- X ^] :ta, current word is tag\n");
- X
- X windgoto(helprow = Rows-2, 47);
- X longline("<Press space bar to continue>\n");
- X windgoto(helprow = Rows-1, 47);
- X longline("<Any other key will quit>");
- X
- X if ( vgetc() != ' ' )
- X return TRUE;
- X
- X/***********************************************************************
- X * Sixth Screen: Operators, Misc. operations, Yank & Put
- X ***********************************************************************/
- X
- X outstr(T_ED);
- X windgoto(helprow = 0, 0);
- X
- longline("\
- X Operators (double to affect lines)\n\
- X ==================================\n\
- X d delete\n\
- X c change\n");
- longline("\
- X < left shift\n\
- X > right shift\n\
- X y yank to buffer\n");
- X
- longline("\n\
- X Miscellaneous operations\n\
- X ========================\n\
- X C change rest of line\n\
- X D delete rest of line\n\
- X s substitute chars\n");
- longline("\
- X S substitute lines (not yet)\n\
- X J join lines\n\
- X x delete characters\n\
- X X ... before cursor\n");
- X
- longline("\n\
- X Yank and Put\n\
- X ============\n\
- X p put back text\n\
- X P put before\n\
- X Y yank lines");
- X
- X windgoto(helprow = Rows-1, 47);
- X longline("<Press any key>");
- X
- X vgetc();
- X
- X return TRUE;
- X}
- X
- static void
- longline(p)
- char *p;
- X{
- X char *s;
- X
- X for ( s = p; *s ;s++ ) {
- X if ( *s == '\n' )
- X windgoto(++helprow, 0);
- X else
- X outchar(*s);
- X }
- X}
- X#else
- X
- bool_t
- help()
- X{
- X msg("Sorry, help not configured");
- X return FALSE;
- X}
- X#endif
- END_OF_FILE
- if test 8348 -ne `wc -c <'help.c'`; then
- echo shar: \"'help.c'\" unpacked with wrong size!
- fi
- # end of 'help.c'
- fi
- if test -f 'main.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'main.c'\"
- else
- echo shar: Extracting \"'main.c'\" \(6750 characters\)
- sed "s/^X//" >'main.c' <<'END_OF_FILE'
- X/*
- X * STEVIE - ST Editor for VI Enthusiasts ...Tim Thompson...twitch!tjt...
- X *
- X * Extensive modifications by: Tony Andrews onecom!wldrdg!tony
- X *
- X */
- X
- X#include "stevie.h"
- X
- int Rows; /* Number of Rows and Columns */
- int Columns; /* in the current window. */
- X
- char *Realscreen = NULL; /* What's currently on the screen, a single */
- X /* array of size Rows*Columns. */
- char *Nextscreen = NULL; /* What's to be put on the screen. */
- X
- char *Filename = NULL; /* Current file name */
- X
- LPTR *Filemem; /* The contents of the file, as a single array. */
- X
- LPTR *Fileend; /* Pointer to the end of the file in Filemem. */
- X /* (It points to the byte AFTER the last byte.) */
- X
- LPTR *Topchar; /* Pointer to the byte in Filemem which is */
- X /* in the upper left corner of the screen. */
- X
- LPTR *Botchar; /* Pointer to the byte in Filemem which is */
- X /* just off the bottom of the screen. */
- X
- LPTR *Curschar; /* Pointer to byte in Filemem at which the */
- X /* cursor is currently placed. */
- X
- int Cursrow, Curscol; /* Current position of cursor */
- X
- int Cursvcol; /* Current virtual column, the column number of */
- X /* the file's actual line, as opposed to the */
- X /* column number we're at on the screen. This */
- X /* makes a difference on lines that span more */
- X /* than one screen line. */
- X
- int Curswant = 0; /* The column we'd like to be at. This is used */
- X /* try to stay in the same column through up/down */
- X /* cursor motions. */
- X
- bool_t set_want_col; /* If set, then update Curswant the next time */
- X /* through cursupdate() to the current virtual */
- X /* column. */
- X
- int State = NORMAL; /* This is the current state of the command */
- X /* interpreter. */
- X
- int Prenum = 0; /* The (optional) number before a command. */
- X
- LPTR *Insstart; /* This is where the latest insert/append */
- X /* mode started. */
- X
- bool_t Changed = 0; /* Set to 1 if something in the file has been */
- X /* changed and not written out. */
- X
- bool_t Debug = 0;
- X
- char Redobuff[1024]; /* Each command should stuff characters into this */
- X /* buffer that will re-execute itself. */
- X
- char Undobuff[1024]; /* Each command should stuff characters into this */
- X /* buffer that will undo its effects. */
- X
- char Insbuff[1024]; /* Each insertion gets stuffed into this buffer. */
- X
- LPTR *Uncurschar; /* Curschar is restored to this before undoing. */
- X
- int Ninsert = 0; /* Number of characters in the current insertion. */
- int Undelchars = 0; /* Number of characters to delete, when undoing. */
- char *Insptr = NULL;
- X
- char **files; /* list of input files */
- int numfiles; /* number of input files */
- int curfile; /* number of the current file */
- X
- static void
- usage()
- X{
- X fprintf(stderr, "usage: stevie [file ...]\n");
- X fprintf(stderr, " stevie -t tag\n");
- X fprintf(stderr, " stevie +[num] file\n");
- X fprintf(stderr, " stevie +/pat file\n");
- X exit(1);
- X}
- X
- main(argc,argv)
- int argc;
- char *argv[];
- X{
- X char *initstr, *getenv(); /* init string from the environment */
- X char *tag = NULL; /* tag from command line */
- X char *pat = NULL; /* pattern from command line */
- X int line = -1; /* line number from command line */
- X
- X /*
- X * Process the command line arguments.
- X */
- X if (argc > 1) {
- X switch (argv[1][0]) {
- X
- X case '-': /* -t tag */
- X if (argv[1][1] != 't')
- X usage();
- X
- X if (argv[2] == NULL)
- X usage();
- X
- X Filename = NULL;
- X tag = argv[2];
- X numfiles = 1;
- X break;
- X
- X case '+': /* +n or +/pat */
- X if (argv[1][1] == '/') {
- X if (argv[2] == NULL)
- X usage();
- X Filename = strsave(argv[2]);
- X pat = &(argv[1][1]);
- X numfiles = 1;
- X
- X } else if (isdigit(argv[1][1]) || argv[1][1] == NUL) {
- X if (argv[2] == NULL)
- X usage();
- X Filename = strsave(argv[2]);
- X numfiles = 1;
- X
- X line = (isdigit(argv[1][1])) ?
- X atoi(&(argv[1][1])) : 0;
- X } else
- X usage();
- X
- X break;
- X
- X default: /* must be a file name */
- X Filename = strsave(argv[1]);
- X files = &(argv[1]);
- X numfiles = argc - 1;
- X break;
- X }
- X } else {
- X Filename = NULL;
- X numfiles = 1;
- X }
- X curfile = 0;
- X
- X windinit();
- X
- X /*
- X * Allocate LPTR structures for all the various position pointers
- X */
- X if ((Filemem = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
- X fprintf(stderr, "Can't allocate data structures\n");
- X windexit(0);
- X }
- X if ((Fileend = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
- X fprintf(stderr, "Can't allocate data structures\n");
- X windexit(0);
- X }
- X if ((Topchar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
- X fprintf(stderr, "Can't allocate data structures\n");
- X windexit(0);
- X }
- X if ((Botchar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
- X fprintf(stderr, "Can't allocate data structures\n");
- X windexit(0);
- X }
- X if ((Curschar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
- X fprintf(stderr, "Can't allocate data structures\n");
- X windexit(0);
- X }
- X if ((Insstart = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
- X fprintf(stderr, "Can't allocate data structures\n");
- X windexit(0);
- X }
- X if ((Uncurschar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
- X fprintf(stderr, "Can't allocate data structures\n");
- X windexit(0);
- X }
- X
- X screenalloc();
- X filealloc(); /* Initialize Filemem & Fileend */
- X
- X screenclear();
- X
- X if ((initstr = getenv("EXINIT")) != NULL) {
- X char *lp, buf[128];
- X
- X if ((lp = getenv("LINES")) != NULL) {
- X sprintf(buf, "%s lines=%s", initstr, lp);
- X readcmdline(':', buf);
- X } else
- X readcmdline(':', initstr);
- X }
- X
- X if (Filename != NULL) {
- X if (readfile(Filename, Filemem, FALSE))
- X filemess("[New File]");
- X } else
- X msg("Empty Buffer");
- X
- X setpcmark();
- X
- X updatescreen();
- X
- X if (tag) {
- X stuffin(":ta ");
- X stuffin(tag);
- X stuffin("\n");
- X
- X } else if (pat) {
- X stuffin(pat);
- X stuffin("\n");
- X
- X } else if (line >= 0) {
- X if (line > 0)
- X stuffnum(line);
- X stuffin("G");
- X }
- X
- X edit();
- X
- X windexit(0);
- X}
- X
- X#define RBSIZE 1280 /* should be a little bigger than YBSIZE */
- static char getcbuff[RBSIZE];
- static char *getcnext = NULL;
- X
- void
- stuffin(s)
- char *s;
- X{
- X if ( getcnext == NULL ) {
- X strcpy(getcbuff,s);
- X getcnext = getcbuff;
- X } else
- X strcat(getcbuff,s);
- X}
- X
- void
- stuffnum(n)
- int n;
- X{
- X char buf[32];
- X
- X sprintf(buf, "%d", n);
- X stuffin(buf);
- X}
- X
- void
- addtobuff(s,c1,c2,c3,c4,c5,c6)
- char *s;
- char c1, c2, c3, c4, c5, c6;
- X{
- X char *p = s;
- X if ( (*p++ = c1) == NUL )
- X return;
- X if ( (*p++ = c2) == NUL )
- X return;
- X if ( (*p++ = c3) == NUL )
- X return;
- X if ( (*p++ = c4) == NUL )
- X return;
- X if ( (*p++ = c5) == NUL )
- X return;
- X if ( (*p++ = c6) == NUL )
- X return;
- X}
- X
- int
- vgetc()
- X{
- X if ( getcnext != NULL ) {
- X int nextc = *getcnext++;
- X if ( *getcnext == NUL ) {
- X *getcbuff = NUL;
- X getcnext = NULL;
- X }
- X return(nextc);
- X }
- X return(inchar());
- X}
- X
- int
- vpeekc()
- X{
- X if ( getcnext != NULL )
- X return(*getcnext);
- X return(-1);
- X}
- X
- X/*
- X * anyinput
- X *
- X * Return non-zero if input is pending.
- X */
- X
- bool_t
- anyinput()
- X{
- X return (getcnext != NULL);
- X}
- END_OF_FILE
- if test 6750 -ne `wc -c <'main.c'`; then
- echo shar: \"'main.c'\" unpacked with wrong size!
- fi
- # end of 'main.c'
- fi
- if test -f 'misccmds.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'misccmds.c'\"
- else
- echo shar: Extracting \"'misccmds.c'\" \(8039 characters\)
- sed "s/^X//" >'misccmds.c' <<'END_OF_FILE'
- X/*
- X * STevie - ST editor for VI enthusiasts. ...Tim Thompson...twitch!tjt...
- X *
- X * Extensive modifications by: Tony Andrews onecom!wldrdg!tony
- X *
- X */
- X
- X#include "stevie.h"
- X
- static void openfwd(), openbwd();
- X
- extern int did_ai;
- X
- X/*
- X * opencmd
- X *
- X * Add a blank line above or below the current line.
- X */
- X
- void
- opencmd(dir, can_ai)
- int dir;
- int can_ai; /* if true, consider auto-indent */
- X{
- X if (dir == FORWARD)
- X openfwd(can_ai);
- X else
- X openbwd(can_ai);
- X}
- X
- static void
- openfwd(can_ai)
- int can_ai;
- X{
- X LINE *l;
- X LPTR *next;
- X char *s; /* string to be moved to new line, if any */
- X
- X /*
- X * If we're in insert mode, we need to move the remainder of the
- X * current line onto the new line. Otherwise the new line is left
- X * blank.
- X */
- X if (State == INSERT)
- X s = &Curschar->linep->s[Curschar->index];
- X else
- X s = "";
- X
- X if ((next = nextline(Curschar)) == NULL) /* open on last line */
- X next = Fileend;
- X
- X /*
- X * By asking for as much space as the prior line had we make sure
- X * that we'll have enough space for any auto-indenting.
- X */
- X if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL)
- X return;
- X
- X if (*s != NUL)
- X strcpy(l->s, s); /* copy string to new line */
- X#if 0
- X else if (can_ai && P(P_AI)) {
- X /*
- X * Auto-indent removed due to buggy implementation...
- X */
- X did_ai = TRUE;
- X }
- X#endif
- X
- X if (State == INSERT) /* truncate current line at cursor */
- X *s = NUL;
- X
- X
- X Curschar->linep->next = l; /* link neighbors to new line */
- X next->linep->prev = l;
- X
- X l->prev = Curschar->linep; /* link new line to neighbors */
- X l->next = next->linep;
- X
- X if (next == Fileend) /* new line at end */
- X l->num = Curschar->linep->num + LINEINC;
- X
- X else if ((l->prev->num) + 1 == l->next->num) /* no gap, renumber */
- X renum();
- X
- X else { /* stick it in the middle */
- X unsigned long lnum;
- X lnum = ((long)l->prev->num + (long)l->next->num) / 2;
- X l->num = lnum;
- X }
- X
- X *Curschar = *nextline(Curschar); /* cursor moves down */
- X Curschar->index = 0;
- X
- X s_ins(Cursrow+1, 1); /* insert a physical line */
- X
- X updatescreen(); /* because Botchar is now invalid... */
- X
- X cursupdate(); /* update Cursrow before insert */
- X}
- X
- static void
- openbwd(can_ai)
- int can_ai;
- X{
- X LINE *l;
- X LPTR *prev;
- X
- X prev = prevline(Curschar);
- X
- X if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL)
- X return;
- X
- X Curschar->linep->prev = l; /* link neighbors to new line */
- X if (prev != NULL)
- X prev->linep->next = l;
- X
- X l->next = Curschar->linep; /* link new line to neighbors */
- X if (prev != NULL)
- X l->prev = prev->linep;
- X
- X#if 0
- X if (can_ai && P(P_AI)) {
- X did_ai = TRUE;
- X }
- X#endif
- X
- X *Curschar = *prevline(Curschar); /* cursor moves up */
- X Curschar->index = 0;
- X
- X if (prev == NULL) /* new start of file */
- X Filemem->linep = l;
- X
- X renum(); /* keep it simple - we don't do this often */
- X
- X cursupdate(); /* update Cursrow before insert */
- X if (Cursrow != 0)
- X s_ins(Cursrow, 1); /* insert a physical line */
- X
- X updatescreen();
- X}
- X
- int
- cntllines(pbegin,pend)
- LPTR *pbegin, *pend;
- X{
- X LINE *lp;
- X int lnum = 1;
- X
- X for (lp = pbegin->linep; lp != pend->linep ;lp = lp->next)
- X lnum++;
- X
- X return(lnum);
- X}
- X
- X/*
- X * plines(p) - return the number of physical screen lines taken by line 'p'
- X */
- int
- plines(p)
- LPTR *p;
- X{
- X register int col;
- X register char *s;
- X
- X s = p->linep->s;
- X
- X if (*s == NUL) /* empty line */
- X return 1;
- X
- X /*
- X * If list mode is on, then the '$' at the end of
- X * the line takes up one extra column.
- X */
- X col = P(P_LS) ? 1 : 0;
- X
- X for (; *s != NUL ;s++) {
- X if ( *s == TAB && !P(P_LS))
- X col += P(P_TS) - (col % P(P_TS));
- X else
- X col += chars[(unsigned)(*s & 0xff)].ch_size;
- X }
- X return ((col + (Columns-1)) / Columns);
- X}
- X
- void
- fileinfo()
- X{
- X long l1, l2;
- X char buf[80];
- X
- X if (bufempty()) {
- X msg("Buffer Empty");
- X return;
- X }
- X
- X l1 = cntllines(Filemem, Curschar);
- X l2 = cntllines(Filemem, Fileend) - 1;
- X sprintf(buf, "\"%s\"%s line %ld of %ld -- %ld %% --",
- X (Filename != NULL) ? Filename : "No File",
- X Changed ? " [Modified]" : "",
- X l1, l2, (l1 * 100)/l2);
- X msg(buf);
- X}
- X
- X/*
- X * gotoline(n) - return a pointer to line 'n'
- X *
- X * Returns a pointer to the last line of the file if n is zero, or
- X * beyond the end of the file.
- X */
- LPTR *
- gotoline(n)
- int n;
- X{
- X static LPTR l;
- X
- X l.index = 0;
- X
- X if ( n == 0 )
- X l = *prevline(Fileend);
- X else {
- X LPTR *p;
- X
- X for (l = *Filemem; --n > 0 ;l = *p)
- X if ((p = nextline(&l)) == NULL)
- X break;
- X }
- X return &l;
- X}
- X
- void
- inschar(c)
- int c;
- X{
- X register char *p, *pend;
- X
- X /* make room for the new char. */
- X if ( ! canincrease(1) )
- X return;
- X
- X p = &Curschar->linep->s[strlen(Curschar->linep->s) + 1];
- X pend = &Curschar->linep->s[Curschar->index];
- X
- X for (; p > pend ;p--)
- X *p = *(p-1);
- X
- X *p = c;
- X
- X /*
- X * If we're in insert mode and showmatch mode is set, then
- X * check for right parens and braces. If there isn't a match,
- X * then beep. If there is a match AND it's on the screen, then
- X * flash to it briefly. If it isn't on the screen, don't do anything.
- X */
- X if (P(P_SM) && State == INSERT && (c == ')' || c == '}' || c == ']')) {
- X LPTR *lpos, csave;
- X
- X if ((lpos = showmatch()) == NULL) /* no match, so beep */
- X beep();
- X else if (LINEOF(lpos) >= LINEOF(Topchar)) {
- X updatescreen(); /* show the new char first */
- X csave = *Curschar;
- X *Curschar = *lpos; /* move to matching char */
- X cursupdate();
- X windgoto(Cursrow, Curscol);
- X delay(); /* brief pause */
- X *Curschar = csave; /* restore cursor position */
- X cursupdate();
- X }
- X }
- X
- X inc(Curschar);
- X CHANGED;
- X}
- X
- void
- insstr(s)
- register char *s;
- X{
- X register char *p, *endp;
- X register int k, n = strlen(s);
- X
- X /* Move everything in the file over to make */
- X /* room for the new string. */
- X if (!canincrease(n))
- X return;
- X
- X endp = &Curschar->linep->s[Curschar->index];
- X p = Curschar->linep->s + strlen(Curschar->linep->s) + 1 + n;
- X
- X for (; p>endp ;p--)
- X *p = *(p-n);
- X
- X p = &Curschar->linep->s[Curschar->index];
- X for ( k=0; k<n; k++ ) {
- X *p++ = *s++;
- X inc(Curschar);
- X }
- X CHANGED;
- X}
- X
- bool_t
- delchar(fixpos)
- bool_t fixpos; /* if TRUE, fix the cursor position when done */
- X{
- X register int i;
- X
- X /* Check for degenerate case; there's nothing in the file. */
- X if (bufempty())
- X return FALSE;
- X
- X if (lineempty()) /* can't do anything */
- X return FALSE;
- X
- X /* Delete the char. at Curschar by shifting everything */
- X /* in the line down. */
- X for ( i=Curschar->index+1; i < Curschar->linep->size ;i++)
- X Curschar->linep->s[i-1] = Curschar->linep->s[i];
- X
- X /* If we just took off the last character of a non-blank line, */
- X /* we don't want to end up positioned at the newline. */
- X if (fixpos) {
- X if (gchar(Curschar)==NUL && Curschar->index>0 && State!=INSERT)
- X Curschar->index--;
- X }
- X CHANGED;
- X
- X return TRUE;
- X}
- X
- X
- void
- delline(nlines)
- X{
- X register LINE *p, *q;
- X int doscreen = TRUE; /* if true, update the screen */
- X
- X /*
- X * There's no point in keeping the screen updated if we're
- X * deleting more than a screen's worth of lines.
- X */
- X if (nlines > (Rows - 1)) {
- X doscreen = FALSE;
- X s_del(Cursrow, Rows-1); /* flaky way to clear rest of screen */
- X }
- X
- X while ( nlines-- > 0 ) {
- X
- X if (bufempty()) /* nothing to delete */
- X break;
- X
- X if (buf1line()) { /* just clear the line */
- X Curschar->linep->s[0] = NUL;
- X Curschar->index = 0;
- X break;
- X }
- X
- X p = Curschar->linep->prev;
- X q = Curschar->linep->next;
- X
- X if (p == NULL) { /* first line of file so... */
- X Filemem->linep = q; /* adjust start of file */
- X Topchar->linep = q; /* and screen */
- X } else
- X p->next = q;
- X q->prev = p;
- X
- X clrmark(Curschar->linep); /* clear marks for the line */
- X
- X /*
- X * Delete the correct number of physical lines on the screen
- X */
- X if (doscreen)
- X s_del(Cursrow, plines(Curschar));
- X
- X /*
- X * If deleting the top line on the screen, adjust Topchar
- X */
- X if (Topchar->linep == Curschar->linep)
- X Topchar->linep = q;
- X
- X free(Curschar->linep->s);
- X free(Curschar->linep);
- X
- X Curschar->linep = q;
- X Curschar->index = 0; /* is this right? */
- X CHANGED;
- X
- X /* If we delete the last line in the file, back up */
- X if ( Curschar->linep == Fileend->linep) {
- X Curschar->linep = Curschar->linep->prev;
- X /* and don't try to delete any more lines */
- X break;
- X }
- X }
- X}
- END_OF_FILE
- if test 8039 -ne `wc -c <'misccmds.c'`; then
- echo shar: \"'misccmds.c'\" unpacked with wrong size!
- fi
- # end of 'misccmds.c'
- fi
- echo shar: End of archive 2 \(of 4\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 4 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-